#include "QueryOptimizer.h"
/** Optimise Clause
   * 
   * @param such that clauses and mapping for order of execution
   * @return Fills the order of executions based on relationship and dependency
   */
int QueryOptimizer::optimizeClause(vector<suchThatClause>& tempSuchThat, vector<int> &suchThatMapping)
{
	vector<int> dependent;
	vector<int> independent;
	for(unsigned int i =0;i<tempSuchThat.size();i++)
	{
		if(tempSuchThat[i].index==-1)
		{
			dependent.push_back(i);
		}
		else
		{
			independent.push_back(i);
		}
	}
	sortByClauseWeight(tempSuchThat,dependent,0,dependent.size()-1);
	sortByClauseWeight(tempSuchThat,independent,0,independent.size()-1);
	suchThatMapping.insert(suchThatMapping.begin(),independent.begin(),independent.end());
	suchThatMapping.insert(suchThatMapping.end(),dependent.begin(),dependent.end());
	return 1;
};
/** Sort Clause By Weight
   * 
   * @param such that clause, independent or dependenct clauses, starting size and ending size of clause
   * @sorts the clause by relationship
   */
int QueryOptimizer::sortByClauseWeight(vector<suchThatClause>& tempSuchThat, vector<int>& clauseDependency,int left, int right)
{

	
	
	if(left<right)
	{
	 int middle = (left+right)/2;
	 sortByClauseWeight(tempSuchThat,clauseDependency,left,middle);
	 sortByClauseWeight(tempSuchThat,clauseDependency,middle+1,right);
	 merge(clauseDependency,tempSuchThat,left,right,middle);
	}
	return 1;
}


void QueryOptimizer::merge(vector<int>& mergeResult,vector<suchThatClause>& tempSuchThat, int left, int right,int middle)
	{
		vector<int> temp;
 int h=left;
 int j=middle + 1;
 int k;
 while((h<=middle)&&(j<=right))
 {
	 if(tempSuchThat[mergeResult[h]].relationshipType<=tempSuchThat[mergeResult[j]].relationshipType)
  {
	  temp.push_back(mergeResult[h]);
   h++;
  }
  else
  {
	  temp.push_back(mergeResult[j]);
   j++;
  }
  
 }
 if(h>middle)
 {
  for(k=j;k<=right;k++)
  {
	  temp.push_back(mergeResult[k]);
   
  }
 }
 else
 {
  for(k=h;k<=middle;k++)
  {
	  temp.push_back(mergeResult[k]);
   
  }
 }
 for(k=0;k<=right-left;k++) mergeResult[k+left] = temp[k];
};

